import {IUIManager} from "./IUIManager";
import {IUIForm} from "./IUIForm";
import {IResourceManager} from "../Resources/IResourceManager";
import {IUIFormHelper} from "./IUIFormHelper";
import GameFrameworkModule from "../Base/GameFrameworkModule";
import Queue from "../../Utils/Queue";
import ccclass = cc._decorator.ccclass;
@ccclass("UIManager")
export class UIManager implements IUIManager,GameFrameworkModule{
    get Priority(): number {
       return 920;
    }
    get baseName(): string {
        return "GameFrameworkModule";
    }

    init(serialIds:Map<number,string>,resdir:string): void {
        this._allloadserialIds = serialIds;
        this._loadedUIForms = new Queue<IUIForm>();
        this._allCacheUIFroms = new Map<string, any>();
        this._respath = resdir;
    }

    private _resourceManager:IResourceManager;
    private _uiFormHelper:IUIFormHelper;
    private _allloadserialIds:Map<number,string>;
    private _loadedUIForms:Queue<IUIForm>;
    private _allCacheUIFroms:Map<string,any>;
    private _respath:string;
    private _isshutdown:boolean;

    CloseUIForm(serialId: number | IUIForm, userdata?): void {
        let peekUI = this.GetCurrentUIForm();
        let removeUI:IUIForm = null;
        if(peekUI == null){
            return;
        }
        if(peekUI == serialId || peekUI.SerialId == serialId){
            removeUI = this._loadedUIForms.dequeue();
        }else {
            let arr = this._loadedUIForms.toArray();
            for (let i = 0; i < arr.length; i++) {
                if (arr[i].SerialId == serialId || arr[i] == serialId) {
                    removeUI = arr[i];
                    arr = arr.splice(i, 1);
                    break;
                }
            }
            this._loadedUIForms.fromArray(arr);
        }
        removeUI?.OnClose(this._isshutdown,userdata);
        this._uiFormHelper.ReleaseUIForm(removeUI);
        this.RefreshDepth();
    }

    GetAllLoadedUIForms(): IUIForm[] {
        return this._loadedUIForms.toArray();
    }

    GetUIForm(serialId: number): IUIForm {
        let arr = this._loadedUIForms.toArray();
        for (let i = 0; i < arr.length;i++){
            if(arr[i].SerialId == serialId){
                return arr[i];
            }
        }
        return null;
    }

    HasUIForm(serialId: number): boolean {
        let arr = this._loadedUIForms.toArray();
        for (let i = 0; i < arr.length;i++){
            if(arr[i].SerialId == serialId){
                return true;
            }
        }
        return false;
    }

    OpenUIForm(serialId: number, userdata?): number {
        if(this._resourceManager == null){
            throw new Error("_resourceManager is null");
        }
        if(this._uiFormHelper == null){
            throw new Error("_uiFormHelper is null");
        }
        if(!this.HasSerialId(serialId)){
            throw new Error("UI serialId is null");
        }
        let assetName:string = this._allloadserialIds.get(serialId);
        let uiPrefab = this._allCacheUIFroms.get(assetName);
        if(uiPrefab == null){
            let self = this;
            this._resourceManager.loadUIAsset(this._respath+assetName,((error, assets) => {
                if(error){
                    return;
                }
                uiPrefab = self._uiFormHelper.InstantiateUIForm(assets);
                self._allCacheUIFroms.set(assetName,uiPrefab);
                self.InternalOpenUIForm(serialId,assetName,uiPrefab,userdata);
            }))
        }else{
            this.InternalOpenUIForm(serialId,assetName,uiPrefab,userdata);
        }
        return serialId;
    }

    SetResourceManager(resourceManager: IResourceManager): void {
        this._resourceManager = resourceManager;
    }

    SetUIFormHelper(uiFormHelper: IUIFormHelper): void {
        this._uiFormHelper = uiFormHelper;
    }
    Update(elapseSeconds: number, realElapseSeconds: number): void {
        let arr = this._loadedUIForms.toArray();
        for (let i = 0; i < arr.length;i++){
            arr[i].OnUpdate(elapseSeconds,realElapseSeconds);
        }
    }
    Shutdown(): void {
        this._isshutdown = true;
        this._loadedUIForms.Clear();
        this._allloadserialIds.clear();
        this._allCacheUIFroms.clear();
        this._respath = null;
        this._resourceManager = null;
        this._uiFormHelper = null;
    }

    private HasSerialId(serialId:number){
        return this._allloadserialIds.has(serialId);
    }

    private InternalOpenUIForm(serialId:number,uiFormAssetName:string,uiPrefab,userdata?){

        let uiForm:IUIForm = this._uiFormHelper.CreateUIForm(uiPrefab,userdata);
        uiForm.OnInit(serialId,uiFormAssetName,userdata);
        this._loadedUIForms.enqueue(uiForm);
        uiForm.OnOpen(userdata);
        this.RefreshDepth();
    }


    private RefreshDepth(){
        let depth:number = 0;
        let arr = this._loadedUIForms.toArray();
        for (let i = 0; i < arr.length;i++){
            arr[i].OnDepthChanged(depth++);
        }
    }

    GetCurrentUIForm(): IUIForm {
        let popUI:IUIForm = this._loadedUIForms.peek() == null?null:this._loadedUIForms.peek().item;
        return popUI;
    }

}